package me.zhengjie.pay.rest;

import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.exception.ValidationException;

import com.wechat.pay.java.core.notification.NotificationConfig;

import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import com.wechat.pay.java.service.refund.model.Status;
import me.zhengjie.annotation.rest.AnonymousGetMapping;
import me.zhengjie.config.WechatPayConfig;
import me.zhengjie.inter.service.MpZhsqService;
import me.zhengjie.pay.domain.JjzhWxPayOrders;
import me.zhengjie.pay.service.JjzhWxPayOrdersService;
import me.zhengjie.pay.service.dto.JjzhWxPayOrdersQueryCriteria;
import me.zhengjie.service.impl.GeneratorServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;


@RestController
@RequestMapping("/api/wxpay")
public class WxPayNotifyController {

    private static final Logger logger = LoggerFactory.getLogger(WxPayNotifyController.class);

    @Autowired
    private WechatPayConfig wechatPayConfig;

    @Autowired
    private JjzhWxPayOrdersService jjzhWxPayOrdersService;

    @Autowired
    private MpZhsqService mpZhsqService;

    /**
     * 支付回调通知
     */
    @PostMapping("/transaction/notify")
    @AnonymousGetMapping // 支持匿名访问
    public ResponseEntity<String> handleWxPayNotify(
            @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
            @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
            @RequestHeader("Wechatpay-Nonce") String wechatpayNonce,
            @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
            @RequestHeader("Wechatpay-Signature-Type") String wechatpaySignatureType,
            HttpServletRequest request) throws IOException {

        // 记录请求信息
        logger.info("收到微信支付回调通知，头信息：Signature={} Serial={} Nonce={} Timestamp={} Signature-Type={}",
                wechatpaySignature, wechatpaySerial, wechatpayNonce, wechatpayTimestamp, wechatpaySignatureType);

        long startTime = System.currentTimeMillis(); // 记录处理开始时间

        // 读取请求体
        InputStream inputStream = request.getInputStream();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;

        while ((length = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, length);
        }
        String rawBody = new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8);
        logger.debug("微信支付回调请求体：{}", rawBody);

        // 构建 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatpaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatpaySignature)
                .timestamp(wechatpayTimestamp)
                .body(rawBody)
                .build();

        // 配置微信支付的通知解析
        NotificationConfig config = (NotificationConfig) wechatPayConfig.getNotificationConfig();
        NotificationParser parser = new NotificationParser(config);

        try {
            // 解析回调通知
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            if (transaction != null) {
                logger.info("解析到微信支付交易信息：{}", transaction);

                // 处理支付成功的业务逻辑
                String outTradeNo = transaction.getOutTradeNo();      // 商户订单号
                JjzhWxPayOrders order = jjzhWxPayOrdersService.findByOrderNo(outTradeNo);
                order.setNotifyData(JSONObject.toJSONString(transaction)); // 保存回调数据

                String transactionId = transaction.getTransactionId(); // 微信支付交易号
                order.setTransactionId(transactionId);

                // 处理支付状态
                if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
                    // 获取支付成功时间并转换为Timestamp
                    String successTime = transaction.getSuccessTime();
                    OffsetDateTime odt = OffsetDateTime.parse(successTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
                    Timestamp payTime = Timestamp.from(odt.toInstant());
                    order.setPayTime(payTime);

                    order.setStatus(1L); // 支付成功
                    mpZhsqService.updateZhsqPayStatus("1", order.getBisZhsqId()); // 更新支付状态
                    logger.info("支付成功，订单号：{}，支付时间：{}", outTradeNo, payTime);
                } else {
                    order.setStatus(3L); // 支付失败
                    order.setRefundReason(transaction.getTradeStateDesc()); // 退款原因
                    logger.warn("支付失败，订单号：{}，状态描述：{}", outTradeNo, transaction.getTradeStateDesc());
                }

                // 更新订单
                jjzhWxPayOrdersService.update(order);

                long endTime = System.currentTimeMillis();
                logger.info("处理支付回调成功，订单号：{}，耗时：{} ms", outTradeNo, (endTime - startTime));

                return ResponseEntity.status(HttpStatus.OK).body("SUCCESS");
            } else {
                logger.error("解析回调数据失败，无法获取支付信息");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("FAILURE");
            }
        } catch (ValidationException e) {
            logger.error("签名验证失败，签名类型：{}", wechatpaySignatureType, e);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("SIGNATURE_VERIFICATION_FAILED");
        } catch (Exception e) {
            logger.error("处理支付回调失败，异常信息：", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("INTERNAL_SERVER_ERROR");
        }
    }

    /**
     * 退款回调通知
     */
    @PostMapping("/refundNotification/notify")
    @AnonymousGetMapping // 支持匿名访问
    public ResponseEntity<String> handleWxPayRefundNotify(
            @RequestHeader("Wechatpay-Signature") String wechatpaySignature,
            @RequestHeader("Wechatpay-Serial") String wechatpaySerial,
            @RequestHeader("Wechatpay-Nonce") String wechatpayNonce,
            @RequestHeader("Wechatpay-Timestamp") String wechatpayTimestamp,
            @RequestHeader("Wechatpay-Signature-Type") String wechatpaySignatureType,
            HttpServletRequest request) throws IOException {

        logger.info("收到微信支付退款回调通知，头信息：Signature={} Serial={} Nonce={} Timestamp={} Signature-Type={}",
                wechatpaySignature, wechatpaySerial, wechatpayNonce, wechatpayTimestamp, wechatpaySignatureType);

        long startTime = System.currentTimeMillis(); // 记录处理开始时间

        // 读取请求体
        InputStream inputStream = request.getInputStream();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int length;

        while ((length = inputStream.read(buffer)) != -1) {
            byteArrayOutputStream.write(buffer, 0, length);
        }
        String rawBody = new String(byteArrayOutputStream.toByteArray(), StandardCharsets.UTF_8);
        logger.debug("微信退款回调请求体：{}", rawBody);

        // 构建 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatpaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatpaySignature)
                .timestamp(wechatpayTimestamp)
                .body(rawBody)
                .build();

        // 配置微信支付的通知解析
        NotificationConfig config = (NotificationConfig) wechatPayConfig.getNotificationConfig();
        NotificationParser parser = new NotificationParser(config);

        try {
            // 解析退款回调通知
            RefundNotification refundNotification = parser.parse(requestParam, RefundNotification.class);
            if (refundNotification != null) {
                logger.info("解析到微信退款信息：{}", refundNotification);



                String outTradeNo = refundNotification.getOutTradeNo();  // 商户订单号
                JjzhWxPayOrders order = jjzhWxPayOrdersService.findByOrderNo(outTradeNo);

                // 根据退款状态更新订单状态
                Status refundStatus = refundNotification.getRefundStatus();
                long status = 3; // 默认状态为退款失败

                switch (refundStatus) {
                    case SUCCESS: // 退款成功
                        String successTime = refundNotification.getSuccessTime();
                        OffsetDateTime odt = OffsetDateTime.parse(successTime, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
                        Timestamp refundTime = Timestamp.from(odt.toInstant());
                        order.setRefundTime(refundTime);
                        status = 3; // 退款成功
                        break;
                    case PROCESSING: // 退款处理中
                        status = 2;
                        break;
                    case CLOSED: // 退款关闭
                    case ABNORMAL: // 退款异常
                        status = 4;
                        break;
                }

                // 保存退款通知数据
                order.setRefundNotifyData(JSONObject.toJSONString(refundNotification));
                order.setStatus(status);
                String refundId = refundNotification.getRefundId(); // 退款单号
                order.setRefundId(refundId);
                
                // 更新订单
                jjzhWxPayOrdersService.update(order);

                long endTime = System.currentTimeMillis();
                logger.info("处理退款回调成功，订单号：{}，退款状态：{}，耗时：{} ms", outTradeNo, refundStatus, (endTime - startTime));

                return ResponseEntity.status(HttpStatus.OK).body("SUCCESS");
            } else {
                logger.error("解析退款回调数据失败，无法获取退款信息");
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("FAILURE");
            }
        } catch (ValidationException e) {
            logger.error("签名验证失败，签名类型：{}", wechatpaySignatureType, e);
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("SIGNATURE_VERIFICATION_FAILED");
        } catch (Exception e) {
            logger.error("处理退款回调失败，异常信息：", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("INTERNAL_SERVER_ERROR");
        }
    }
}
